using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;

namespace SPGE
{
    public class ResourceGroupHandler
    {
        internal Dictionary<string, List<IScene>> Groups = new Dictionary<string,List<IScene>>();
        internal Dictionary<string, bool> GroupLoaded = new Dictionary<string, bool>();
        internal Dictionary<string, object> Items = new Dictionary<string, object>();

        private string LoadSceneGroupName
        { get { return DefaultResourceGroups.LoadScene.ToString(); } }
        private string AlwaysLoadedGroupName
        { get { return DefaultResourceGroups.AlwaysLoaded.ToString(); } }

        #region Ctors
        public ResourceGroupHandler(int numberOfGroups, Func<KeyValuePair<string, List<IScene>>> getGroup)
        {
            for (int i = 0; i < numberOfGroups; i++)
            {
                var group = getGroup();
                Groups.Add(group.Key, group.Value);
                GroupLoaded.Add(group.Key, false);
            }

            SetupDefaultGroups();
        }

        public ResourceGroupHandler(List<string> groupNames, Func<string, List<IScene>> getGroup)
        {
            foreach (var name in groupNames)
            {
                Groups.Add(name, getGroup(name));
                GroupLoaded.Add(name, false);
            }

            SetupDefaultGroups();
        }

        private void SetupDefaultGroups()
        {
            if (!Groups.ContainsKey(LoadSceneGroupName))
            {
                Groups.Add(LoadSceneGroupName, new List<IScene>());
                GroupLoaded.Add(LoadSceneGroupName, false);
            }
            if (!Groups.ContainsKey(AlwaysLoadedGroupName))
            {
                Groups.Add(AlwaysLoadedGroupName, new List<IScene>());
                GroupLoaded.Add(AlwaysLoadedGroupName, false);
            }
        }
        #endregion

        public void LoadGroup(string name, ContentManager cm)
        {
            if(!GroupLoaded.ContainsKey(name))
                return;

            if (!GroupLoaded[name])
            {
                var group = Groups[name];

                foreach (var scene in group)
                {
                    scene.Initialize();

                    scene.Load(this);
                }

                GroupLoaded[name] = true;
            }

            if (!GroupLoaded[LoadSceneGroupName])
                LoadGroup(DefaultResourceGroups.LoadScene.ToString(), cm);
            if (!GroupLoaded[AlwaysLoadedGroupName])
                LoadGroup(DefaultResourceGroups.AlwaysLoaded.ToString(), cm);

#if DEBUG
            else
                throw new Exception(String.Format("Group {0} already loaded", name));
#endif
        }

        public void LoadFirstGroupWith(IScene scene, ContentManager cm)
        {
            List<string> names = GetGroupsWith(scene);

            LoadGroup(names[0], cm);
        }

        public void UnloadGroup(string name)
        {
            if (GroupLoaded[name] && name != DefaultResourceGroups.LoadScene.ToString() && name != DefaultResourceGroups.AlwaysLoaded.ToString())
            {
                var group = Groups[name];

                foreach (var scene in group)
                {
                    scene.Unload();
                    GroupLoaded[name] = false;
                }
            }
#if DEBUG
            else
                throw new Exception(String.Format("Group {0} already unloaded", name));
#endif
        }

        private List<string> GetGroupsWith(IScene scene)
        {
            List<string> names = new List<string>();

            foreach (var name in Groups.Keys)
            {
                var group = Groups[name];

                foreach (var sc in group)
                    if (sc == scene)
                    {
                        names.Add(name);
                        break;
                    }
            }
            return names;
        }

        public bool IsLoaded(IScene scene)
        {
            var groups = GetGroupsWith(scene);

            foreach (var name in groups)
                if (GroupLoaded[name])
                    return true;

            return false;
        }

        public bool IsLoaded(string groupName)
        {
            return GroupLoaded[groupName];
        }

        public T LoadItem<T>(string path)
        {
            if (Items.ContainsKey(path))
                return (T)Items[path];
            else
            {
                var item = GameContainer.ContentManager.Load<T>(path);

                Items.Add(path, item);

                return item;
            }
        }

        internal void LoadLoadingGroup(ContentManager cm)
        {
            var loadScene = DefaultResourceGroups.LoadScene.ToString();
            if (GroupLoaded.ContainsKey(loadScene) && !GroupLoaded[loadScene])
            {
                var group = Groups[loadScene];

                foreach (var scene in group)
                {
                    scene.Initialize();

                    scene.Load(this);
                }

                GroupLoaded[loadScene] = true;
            }
        }
    }
}
